/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.cam.can.watermarking;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import uk.ac.cam.can.Data;
import uk.ac.cam.can.algorithm.PosGen;

/**
 *
 * @author Thomas
 */
public class Watermark {
    private static String[] university = {"Bachelors", "Masters", "Doctorate"};
    private static String[] pro = {"Prof-school", "Assoc-acdm", "Assoc-voc", "Some-college"};
    private static String[] elementary = {"Preschool", "1st-4th"};
    private static String[] midleschool = {"5th-6th", "7th-8th", "9th"};
    private static String[] highschool = {"10th", "11th", "12th", "HS-grad"};
    
    private static String[] higher = {"University", "Pro"};
    private static String[] lower = {"Elementary", "Midleschool", "Highschool"};
    
    private static String[] education = {"Lower, Higher"};
    
    private static String[] single = {"Never-married", "Divorced", "Widowed", "Separated"};
    private static String[] married = {"Married-civ-spouse", "Married-AF-spouse", "Married-spouse-absent"};
    
    private static String[] marritalStatus = {"SINGLE", "MARRIED"};
    
    private static int C=200;
    
    public static void mark(Data data, long key) throws IOException{
        // build the q groups
        data.load();
        Map<String, List<String[]>> qgroups = new HashMap<String, List<String[]>>();
        for(String[] record : data.getRecords()){
            String qi="";
            for(int i = 0; i < data.nbAttributes(); i++){
                if(data.getType(i)==Data.TYPE_QUASI_IDENTIFIER)
                    qi+=record[i];
            }
            if(qgroups.containsKey(qi)){
                qgroups.get(qi).add(record);
            }else{
                //System.out.println(qi);
                qgroups.put(qi, new ArrayList<String[]>());
                qgroups.get(qi).add(record);
            }            
        }
        int marked = 0;
        List<String[]> records = new ArrayList<String[]>();
        for(List<String[]> group : qgroups.values()){

            for(String[] record : group){
                long id = Long.valueOf(record[0]);
                long seed = key+id;
                Random rand = new Random(seed);
                if(rand.nextInt()%C==0){
                    int attribute = 4+rand.nextInt(2);
                    String[] marks = findCategory(group.get(0)[attribute]);
                    if(marks==null)
                        continue;
                    marked++;
                    int pos = rand.nextInt(marks.length);
                    for(String[] r : group){
                        r[attribute]=marks[pos];

                    }
                    break;
                }
                records.addAll(group);
            }
        }
        
        File f = new File("./tmp/marked");
        f.delete();
        BufferedWriter buff = new BufferedWriter(new FileWriter("./tmp/marked"));
        for(String[] record : records){
            String line="";
            for(String a : record){
                line+=a+",";
            }
            buff.write(line);
            buff.newLine();
        }
        buff.flush();
        buff.close();
    
    }
    
    public static double checkMark(Data data, long key){
        data.load();
        Map<String, List<String[]>> qgroups = new HashMap<String, List<String[]>>();
        for(String[] record : data.getRecords()){
            String qi="";
            for(int i = 0; i < data.nbAttributes(); i++){
                if(data.getType(i)==Data.TYPE_QUASI_IDENTIFIER)
                    qi+=record[i];
            }
            if(qgroups.containsKey(qi)){
                qgroups.get(qi).add(record);
            }else{
                //System.out.println(qi);
                qgroups.put(qi, new ArrayList<String[]>());
                qgroups.get(qi).add(record);
            }            
        }
        int marked = 0;
        int total = 0;
        
        
        for(List<String[]> group : qgroups.values()){
                for(String[] record : group){
                    long id = Long.valueOf(record[0]);
                    long seed = key+id;
                    Random rand = new Random(seed);
                    
                    if(rand.nextInt()%C==0){
                        int attribute = 4+rand.nextInt(2);
                        String[] marks = findCategory(group.get(0)[attribute]);
                        if(marks==null)
                            continue;
                        total++;
                        int pos = rand.nextInt(marks.length);
                        if(group.get(0)[attribute].equals(marks[pos]))
                            marked++;
                        break;
                    }
            }
        }
        return (double)marked/(double)total;
    }
    
    private static String[] findCategory(String value){
        if(value.equals("*")){
            return null;
        }
        for(String target : higher){
            if(value.contains(target))
                return higher;
        }
        for(String target : elementary){
            if(value.contains(target))
                return elementary;
        }
        for(String target : midleschool){
            if(value.contains(target))
                return midleschool;
        }
        for(String target : lower){
            if(value.contains(target))
                return lower;
        }
        for(String target : university){
            if(value.contains(target))
                return university;
        }
        for(String target : pro){
            if(value.contains(target))
                return pro;
        }        
        
        for(String target : highschool){
            if(value.contains(target))
                return highschool;
        }
        
        for(String target : education){
            if(value.contains(target))
                return education;
        }
        
        for(String target : single){
            if(value.contains(target))
                return single;
        }
        for(String target : married){
            if(value.contains(target))
                return married;
        }
        for(String target : marritalStatus){
            if(value.contains(target))
                return married;
        }
        
        
        return null;
    }
    
    public static void randomAlteration(double d, Data data){
        Random rand = new Random(System.nanoTime());
        int target = (int)(data.size()*d);
        for(int i = 0; i < target; i++){
            int attribute = 4+rand.nextInt(2);
            int pos = rand.nextInt(data.getRecords().size());            
            String[] cat = findCategory(data.getRecords().get(pos)[attribute]);
            if(cat==null)
                continue;
            int p = rand.nextInt(cat.length);
            data.getRecords().get(pos)[attribute]=cat[p];
        }
    }
    
    public static void addRandom(double d, Data data){
        Random rand = new Random(System.nanoTime());
        int target = (int)(data.size()*d);
        
        for(int i = 0; i < target; i++){
            String[] record = new String[data.nbAttributes()];
            record[0]=""+rand.nextInt();
            record[4]=married[rand.nextInt(married.length)];
            record[5]=married[rand.nextInt(married.length)];
            data.getRecords().add(record);
        }
    }
}
